CIE: Add "CIE L float"
authorDebarshi Ray <debarshir@gnome.org>
Thu, 9 Nov 2017 06:48:26 +0000 (07:48 +0100)
committerDebarshi Ray <debarshir@gnome.org>
Sat, 11 Nov 2017 20:03:58 +0000 (21:03 +0100)
Some of these conversions will be leveraged by gegl:shadows-highlights
which needs to go from "Y float" or "YaA float" to "CIE L float".

The conversion from "RGBA float" was added to aid "YaA float" to
"CIE L float" fishes. They go via:
  "YaA float"     to "RaGaBaA float"
  "RaGaBaA float" to "RGBA float"
  "RGBA float"    to "Y float"
  "Y float"       to "CIE L float"

A direct conversion from "YaA float" to "Y float" in simple C is
hindered by the need to check every pixel's alpha value to avoid
dividing by zero. The pipeline stalls make it lose out to the look-up
table and SIMD based RGB conversions to unassociated alpha.

However, we can trivially cut out the third step and still reduce some
memory traffic.

https://bugzilla.gnome.org/show_bug.cgi?id=790111

extensions/CIE.c

index 60d480b295171a50f5836a1d473697c5601c8032..658fd2a8b304f2c2c9a6b87adaed18e47ccaa614 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 2005, 2014 Øyvind Kolås.
  * Copyright (C) 2009, Martin Nordholts
  * Copyright (C) 2014, Elle Stone
+ * Copyright (C) 2017, Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -591,6 +592,44 @@ cubef (float f)
   return f * f * f;
 }
 
+static void
+Yf_to_Lf (const Babl *conversion,float *src,
+          float *dst,
+          long   samples)
+{
+  long n = samples;
+
+  while (n--)
+    {
+      float yr = src[0];
+      float L  = yr > LAB_EPSILON ? 116.0f * _cbrtf (yr) - 16 : LAB_KAPPA * yr;
+
+      dst[0] = L;
+
+      src++;
+      dst++;
+    }
+}
+
+static void
+Yaf_to_Lf (const Babl *conversion,float *src,
+           float *dst,
+           long   samples)
+{
+  long n = samples;
+
+  while (n--)
+    {
+      float yr = src[0];
+      float L  = yr > LAB_EPSILON ? 116.0f * _cbrtf (yr) - 16 : LAB_KAPPA * yr;
+
+      dst[0] = L;
+
+      src += 2;
+      dst += 1;
+    }
+}
+
 static void
 Yaf_to_Laf (const Babl *conversion,float *src,
             float *dst,
@@ -656,6 +695,36 @@ rgbf_to_Labf (const Babl *conversion,float *src,
     }
 }
 
+static void
+rgbaf_to_Lf (const Babl *conversion,float *src,
+             float *dst,
+             long   samples)
+{
+  const Babl *space = babl_conversion_get_source_space (conversion);
+  float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Y;
+  float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Y;
+  float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Y;
+  long n = samples;
+
+  while (n--)
+    {
+      float r = src[0];
+      float g = src[1];
+      float b = src[2];
+
+      float yr = m_1_0 * r + m_1_1 * g + m_1_2 * b;
+
+      float fy = yr > LAB_EPSILON ? _cbrtf (yr) : (LAB_KAPPA * yr + 16.0f) / 116.0f;
+
+      float L = 116.0f * fy - 16.0f;
+
+      dst[0] = L;
+
+      src += 4;
+      dst += 1;
+    }
+}
+
 static void
 rgbaf_to_Labf (const Babl *conversion,float *src,
                float *dst,
@@ -746,6 +815,38 @@ rgbaf_to_Labaf (const Babl *conversion,float *src,
     }
 }
 
+static void
+Labf_to_Lf (const Babl *conversion,float *src,
+            float *dst,
+            long   samples)
+{
+  long n = samples;
+
+  while (n--)
+    {
+      dst[0] = src[0];
+
+      src += 3;
+      dst += 1;
+    }
+}
+
+static void
+Labaf_to_Lf (const Babl *conversion,float *src,
+             float *dst,
+             long   samples)
+{
+  long n = samples;
+
+  while (n--)
+    {
+      dst[0] = src[0];
+
+      src += 4;
+      dst += 1;
+    }
+}
+
 static void
 Labf_to_rgbf (const Babl *conversion,float *src,
                 float *dst,
@@ -1005,12 +1106,42 @@ conversions (void)
     "linear", Labaf_to_rgbaf,
     NULL
   );
+  babl_conversion_new (
+    babl_format ("Y float"),
+    babl_format ("CIE L float"),
+    "linear", Yf_to_Lf,
+    NULL
+  );
+  babl_conversion_new (
+    babl_format ("YA float"),
+    babl_format ("CIE L float"),
+    "linear", Yaf_to_Lf,
+    NULL
+  );
   babl_conversion_new (
     babl_format ("YA float"),
     babl_format ("CIE L alpha float"),
     "linear", Yaf_to_Laf,
     NULL
   );
+  babl_conversion_new (
+    babl_format ("RGBA float"),
+    babl_format ("CIE L float"),
+    "linear", rgbaf_to_Lf,
+    NULL
+  );
+  babl_conversion_new (
+    babl_format ("CIE Lab float"),
+    babl_format ("CIE L float"),
+    "linear", Labf_to_Lf,
+    NULL
+  );
+  babl_conversion_new (
+    babl_format ("CIE Lab alpha float"),
+    babl_format ("CIE L float"),
+    "linear", Labaf_to_Lf,
+    NULL
+  );
   babl_conversion_new (
     babl_model ("RGBA"),
     babl_model ("CIE LCH(ab)"),
@@ -1109,6 +1240,13 @@ formats (void)
     babl_component ("A"),
     NULL);
 
+  babl_format_new (
+    "name", "CIE L float",
+    babl_model ("CIE Lab"),
+    babl_type ("float"),
+    babl_component ("CIE L"),
+    NULL);
+
   babl_format_new (
     "name", "CIE L alpha float",
     babl_model ("CIE Lab alpha"),